﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using ParkService.Ut;

namespace HsPrint.Ut
{
    public class D8API
    {
        #region 对USB接口的使用(PHILIPH卡)
        [DllImport("dcrf32.dll")]
        public static extern int dc_init(Int16 port, Int32 baud);  //初试化

        [DllImport("dcrf32.dll")]
        public static extern short dc_exit(int icdev);
        [DllImport("dcrf32.dll")]
        public static extern short dc_reset(int icdev, uint sec);
        [DllImport("dcrf32.dll")]
        public static extern short dc_request(int icdev, char _Mode, ref uint TagType);

        [DllImport("dcrf32.dll")]
        public static extern short dc_pro_reset(int icdev, ref byte rlen, ref byte rbuff);
        [DllImport("dcrf32.dll")]
        public static extern short dc_pro_reset_hex(int icdev, ref byte rlen, ref byte rbuff);
        [DllImport("dcrf32.dll")]
        public static extern short dc_pro_resethex(int icdev, ref byte rlen, ref byte rbuff);



        [DllImport("dcrf32.dll")]
        public static extern short dc_card(int icdev, char _Mode, ref ulong Snr);
        [DllImport("dcrf32.dll")]
        public static extern short dc_halt(int icdev);
        [DllImport("dcrf32.dll")]
        public static extern short dc_anticoll(int icdev, char _Bcnt, ref ulong IcCardNo);
        [DllImport("dcrf32.dll")]
        public static extern short dc_beep(int icdev, uint _Msec);
        [DllImport("dcrf32.dll")]
        public static extern short dc_config_card(int icdev, char _CardType);
        [DllImport("dcrf32.dll")]
        public static extern short dc_authentication(int icdev, int _Mode, int _SecNr);

        [DllImport("dcrf32.dll")]
        public static extern short dc_load_key(int icdev, int mode, int secnr, [In] byte[] nkey);  //密码装载到读写模块中
        [DllImport("dcrf32.dll")]
        public static extern short dc_load_key_hex(int icdev, int mode, int secnr, string nkey);  //密码装载到读写模块中

        [DllImport("dcrf32.dll")]
        public static extern short dc_write(int icdev, int adr, [In] byte[] sdata);  //向卡中写入数据

        [DllImport("dcrf32.dll")]
        public static extern short dc_write(int icdev, int adr, [In] string sdata);  //向卡中写入数据

        [DllImport("dcrf32.dll")]
        public static extern short dc_write_hex(int icdev, int adr, [In] string sdata);  //向卡中写入数据(转换为16进制)

        [DllImport("dcrf32.dll")]
        public static extern short dc_read(int icdev, int adr, [Out] byte[] sdata);

        [DllImport("dcrf32.dll")]
        public static extern short dc_read(int icdev, int adr, [MarshalAs(UnmanagedType.LPStr)] StringBuilder sdata);  //从卡中读数据
        [DllImport("dcrf32.dll")]
        public static extern short dc_read_hex(int icdev, int adr, [MarshalAs(UnmanagedType.LPStr)] StringBuilder sdata);  //从卡中读数据(转换为16进制)
        [DllImport("dcrf32.dll")]
        public static extern short a_hex(ref byte oldValue, ref byte newValue, int len);  //普通字符转换成十六进制字符
        [DllImport("dcrf32.dll")]
        public static extern void hex_a(ref byte oldValue, ref byte newValue, int len);  //十六进制字符转换成普通字符


        [DllImport("dcrf32.dll")]
        public static extern short dc_request_b(int icdev, byte mode, byte AFI, byte N, ref byte atqb);

        [DllImport("dcrf32.dll")]
        public static extern short dc_attrib(int icdev, ref byte PUPI, byte CID);



        [DllImport("dcrf32.dll")]
        public static extern short dc_pro_command(int icdev, byte len, ref byte sbuff, ref byte rlen, ref byte rbuff, byte tt);
        [DllImport("dcrf32.dll")]
        public static extern short dc_pro_commandlink(int icdev, byte len, ref byte sbuff, ref byte rlen, ref byte rbuff, byte tt, byte FG);
        [DllImport("dcrf32.dll")]
        public static extern short dc_pro_commandlink_hex(int icdev, byte len, ref byte sbuff, ref byte rlen, ref byte rbuff, byte tt, byte FG);
        [DllImport("dcrf32.dll")]
        public static extern short dc_pro_commandsource(int icdev, byte len, ref byte sbuff, ref byte rlen, ref byte rbuff, byte timeout);
        [DllImport("dcrf32.dll")]
        public static extern short dc_pro_commandsourcehex(int icdev, byte len, ref byte sbuff, ref byte rlen, ref byte rbuff, byte timeout);


        [DllImport("dcrf32.dll")]
        public static extern short dc_setcpu(int icdev, byte SAMID);
        [DllImport("dcrf32.dll")]
        public static extern short dc_setcpupara(int icdev, byte cputype, byte cpupro, byte cpuetu);
        [DllImport("dcrf32.dll")]
        public static extern short dc_cpureset_hex(int icdev, ref byte[] rlen, ref byte[] rbuff);//非触式CPU卡复位
        [DllImport("dcrf32.dll")]
        public static extern short dc_cpuapdu_hex(int icdev, [In] byte slen, [In] byte[] senddata, [Out] byte[] rlen, [Out] byte[] databuffer);
        #endregion

        #region 对外提供读卡方法
        /// <summary>
        /// 对外提供读卡方法
        /// </summary>
        public ReacardNumOutput ReadCardId()
        {
            ReacardNumOutput output = new ReacardNumOutput();
            output.msg = "读卡失败!";
            output.ret = 0;
            string CardId = "";
            string UId = "";
            CardPerson persong = new CardPerson();
            try
            {
                short txtPort = 100;
                icdev = D8API.dc_init(txtPort, 115200);
                if (icdev <= 0)
                {
                    output.msg = "初始化读卡器失败!";
                    output.ret = -1;
                    return output;
                }
                else
                {
                    D8API.dc_beep(icdev, 10);
                    int st;
                    st = D8API.dc_reset(icdev, 1);
                    if (st < 0)
                    {
                        output.msg = "初始化读卡器失败!";
                        output.ret = -1;
                        return output;
                    }
                    ulong icCardNo = 0;
                    st = D8API.dc_card(icdev, '0', ref icCardNo);
                    if (st != 0)
                    {
                        output.msg = "寻卡失败,请正确放置卡片!";
                        output.ret = -2;
                        return output;
                    }
                    byte crlen = 1;
                    byte[] recbuff = new byte[100];
                    st = D8API.dc_pro_resethex(icdev, ref crlen, ref recbuff[0]);    
                    if (st != 0)
                    {
                        output.msg = "寻卡失败,请正确放置卡片!";
                        output.ret = -2;
                        return output;
                    }
                    else
                    {
                        string strRetVal = System.Text.Encoding.ASCII.GetString(recbuff).Replace("\0","");
                        if (strRetVal != null && strRetVal.Length > 8)
                        {
                            UId = strRetVal.Substring(strRetVal.Length - 8);
                        }
                    }
                    string ApduResult = string.Empty;
                    //1.SELECT 选择MF
                    ApduResult = RunCommand("00A40000023F00");
                    if (ApduResult.Substring(ApduResult.Length - 4) == "9000")
                    {
                        //2.SELECT 选择AID
                        ApduResult = RunCommand("00A4040009A00000000386980701");

                        #region 读取卡号信息
                        //3.READ BINARY 读0x15文件
                        var Apdu_15_Result = RunCommand("00B0950000");
                        if (!string.IsNullOrEmpty(Apdu_15_Result) && Apdu_15_Result.Substring(Apdu_15_Result.Length - 4) == "9000")
                        {
                            output.issuercode = Apdu_15_Result.Substring(0, 4);//发卡方代码 
                            output.citycode = Apdu_15_Result.Substring(4, 4);//城市代码
                            output.industrycode = Apdu_15_Result.Substring(8, 4);//行业代码
                            output.enable = Apdu_15_Result.Substring(16, 2);//启用标识  00：未启用 01：启用 03：停用
                            switch (output.enable)
                            {
                                case "00":
                                    output.enableName = "未启用";
                                    break;
                                case "01":
                                    output.enableName = "启用";
                                    break;
                                case "02":
                                    output.enableName = "停用";
                                    break;
                            }
                            output.applicationver = Apdu_15_Result.Substring(18, 2); //应用版本
                            output.intercon = Apdu_15_Result.Substring(20, 2); //互联互通标识
                            output.startDate = Apdu_15_Result.Substring(40, 8); //启用日期
                            output.validdate = Apdu_15_Result.Substring(48, 8); //有效日期

                            output.cardType = Apdu_15_Result.Substring(56, 2); //主卡类型(卡类型)
                            string CardNo = Apdu_15_Result.Substring(32, 8); //卡流水号
                            string ChildCardKind = Apdu_15_Result.Substring(58, 2); //子卡类型                            
                            CardNo = Convert.ToInt32(CardNo, 16).ToString().PadLeft(8, '0');
                            CardId = CardNo;
                        }
                        #endregion

                        #region  读取持卡人信息
                        //3.READ BINARY 读0x16文件
                        var Apdu_16Result = RunCommand("00B0960000");
                        if (!string.IsNullOrEmpty(Apdu_16Result) && Apdu_16Result.Substring(Apdu_16Result.Length - 4) == "9000")
                        {
                            string perName = Apdu_16Result.Substring(4, 40);  //姓名
                            string _IdNumber = Apdu_16Result.Substring(44, 64); //证件号
                            persong.fullName = (perName != "0000000000000000000000000000000000000000" && perName != "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") ? ASCtoGB(perName) : "无";
                            persong.certNo = (_IdNumber != "0000000000000000000000000000000000000000000000000000000000000000" && _IdNumber != "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") ? strToIdNumber(_IdNumber) : "无";
                        }
                        if (persong.fullName== "无" && persong.certNo== "无")
                        {
                            //4.READ BINARY 读0x20文件
                            var ApduResult20 = RunCommand("00A40000020020"); //选中20文件
                            var Apdu_20Result = RunCommand("00B0000000");
                            if (!string.IsNullOrEmpty(Apdu_20Result) && Apdu_20Result.Substring(Apdu_20Result.Length - 4) == "9000")
                            {
                                string perName = Apdu_20Result.Substring(6, 40);  //姓名
                                string _IdNumber = Apdu_20Result.Substring(46, 64); //证件号
                                persong.fullName = "无"; //(perName != "0000000000000000000000000000000000000000" && perName != "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") ? ASCtoGB(perName) : "无";
                                persong.certNo = (_IdNumber != "0000000000000000000000000000000000000000000000000000000000000000" && _IdNumber != "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") ? strToIdNumber(_IdNumber) : "无";
                            }
                        }
                        #endregion

                        #region 取得卡余额
                        //取得卡余额
                        var Apdu_00Result1 = RunCommand("805C000204");
                        if (Apdu_00Result1.Substring(Apdu_00Result1.Length - 4) == "9000")
                        {
                            output.balance = (Convert.ToDecimal(HexTo10(Apdu_00Result1.Substring(0, 8)))/100).ToString();
                        }
                        #endregion

                        #region 取得卡交易明细
                        //取得卡交易明细
                        var Apdu_18Result1 = RunCommand("00B201C400");
                        if (Apdu_18Result1.Substring(Apdu_18Result1.Length - 4) == "9000")
                        {
                            var txnNo = Apdu_18Result1.Substring(0, 4);  //交易编号
                            var txnNo1 = Apdu_18Result1.Substring(10, 8);  //交易金额（和上一步算余额的方法一样）
                            var txnNo2 = Apdu_18Result1.Substring(18, 2);  //交易类型
                            var txnNo3 = Apdu_18Result1.Substring(32, 8);  //交易日期
                            var txnNo4 = Apdu_18Result1.Substring(40, 8);  //交易时间
                        }
                        #endregion
                    }
                    else
                    {
                        output.msg = "选择卡片主目录失败,可重试读卡!";
                        output.ret = -3;
                        return output;
                    }
                }
                //关闭
                D8API.dc_exit((Int16)icdev);
            }
            catch(Exception ex)
            {
                //关闭
                D8API.dc_exit((Int16)icdev);
            }
            if (!string.IsNullOrEmpty(CardId) && !string.IsNullOrEmpty(UId) && UId.Length == 8)
            {
                //实现高低位转换
                string[] _str = new string[4];
                _str[0] = UId.Substring(6, 2);
                _str[1] = UId.Substring(4, 2);
                _str[2] = UId.Substring(2, 2);
                _str[3] = UId.Substring(0, 2);
                UId = _str[0] + _str[1] + _str[2] + _str[3];
                output.ret = 1;
                output.msg = "读卡成功";
                output.cardno = Convert.ToInt64(UId, 16).ToString();
                output.catcardno = CardId;
                output.personInfo = persong; //持卡人
            }
            else
            {
                output.ret = 0;
                output.msg = "读卡失败";
            }
            return output;
        }
        private int icdev = -1;
        private byte[] tempGlobal = new byte[64];

        #region 执行APDU命令行
        public string RunCommand(string strm1)
        {
            byte lenm1 = (byte)(strm1.Length / 2);
            byte rlenm1 = 0;
            byte[] sbuffm1 = System.Text.Encoding.ASCII.GetBytes(strm1);
            byte[] rbuffm1 = new byte[300];

            int i = dc_pro_commandlink_hex(icdev, lenm1, ref sbuffm1[0], ref rlenm1, ref rbuffm1[0], 7, 56);
            string Meesm1 = System.Text.Encoding.ASCII.GetString(rbuffm1).Replace("\0", "");
            string Meessm1 = HP_bytetostrremove(rbuffm1, 4);
            if (i != 0 || Meessm1 != "9000")
            {
                dc_exit(icdev);
                return "ERR:" + Meessm1;
            }
            return Meesm1;
        }
        ///// <summary>
        ///// 执行命令行
        ///// </summary>
        ///// <param name="Commandstr"></param>
        ///// <returns></returns>
        //string RunCommand(string Commandstr)
        //{
        //    byte slen;
        //    byte rlen = 1;
        //    byte[] sbuff = new byte[64];
        //    byte[] rbuff = new byte[64];
        //    string RetResult = string.Empty;
        //    if (string.IsNullOrEmpty(Commandstr))
        //    {
        //        return "";
        //    }
        //    slen = (byte)(Commandstr.Length / 2);
        //    string textccc = Commandstr;
        //    sbuff = System.Text.Encoding.ASCII.GetBytes(textccc);
        //    int st = D8API.dc_pro_commandlink_hex(icdev, slen, ref sbuff[0], ref rlen, ref rbuff[0], 7, 56);//后面两参数建议客户使用7和56
        //    if (st != 0)
        //    {
        //        string temstr = "dc_pro_commandlink_hex Error:Error " + st.ToString();
        //        return "";
        //    }
        //    else
        //    {
        //        string textddd = null;
        //        for (int w = 0; w < rbuff.Length; w++)
        //        {
        //            textddd += (char)rbuff[w];
        //        }
        //        RetResult = textddd;
        //    }
        //    return RetResult.Trim().Replace("\0", "");
        //}
        #endregion

        #endregion

        #region 转码方法
        /// <summary>
        /// byte[]变字符取后N个
        /// </summary>
        /// <param name="rbuff"></param>
        /// <returns></returns>
        public static string HP_bytetostrremove(byte[] rbuff, int N)
        {
            string str = "";
            string Mees = System.Text.Encoding.ASCII.GetString(rbuff).Replace("\0", "");
            if (Mees.Length >= 4)
            {
                str = Mees.Remove(0, Mees.Length - N);
            }
            return str;
        }
        public static string ASCtoGB(string card)
        {
            string ddd = HexToASCII(card).Replace(" ", "");
            string Unicodestr = "";
            string[] dssd = SplitByLen(ddd, 4);
            foreach (string i in dssd)
            {
                Unicodestr += "\\u" + i;
            }
            string ddds = Unicode2String(Unicodestr);
            return ddds;
        }
        public static string HexToStr(string Msg)
        {
            byte[] buff = new byte[Msg.Length / 2];
            string Message = "";
            for (int i = 0; i < buff.Length; i++)
            {
                buff[i] = byte.Parse(Msg.Substring(i * 2, 2),
                   System.Globalization.NumberStyles.HexNumber);
            }
            System.Text.Encoding chs = System.Text.Encoding.GetEncoding("gb2312");
            Message = chs.GetString(buff);
            return Message;
        }
        public static string wxHexToASCII(string Msg)
        {
            byte[] buff = new byte[Msg.Length / 2];
            string Message = "";
            for (int i = 0; i < buff.Length; i++)
            {
                buff[i] = byte.Parse(Msg.Substring(i * 2, 2),
                   System.Globalization.NumberStyles.HexNumber);
            }

            System.Text.Encoding chs = System.Text.Encoding.ASCII;
            Message = chs.GetString(buff);
            return Message;
        }
        public static string HexToASCII(string Msg)
        {
            byte[] buff = new byte[Msg.Length / 2];
            string Message = "";
            for (int i = 0; i < buff.Length; i++)
            {
                buff[i] = byte.Parse(Msg.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber);
            }
            System.Text.Encoding chs = System.Text.Encoding.ASCII;
            Message = chs.GetString(buff);
            return Message;
        }
        /// <summary>
        /// Unicode转字符串
        /// </summary>
        /// <param name="source">经过Unicode编码的字符串</param>
        /// <returns>正常字符串</returns>
        public static string Unicode2String(string source)
        {
            return new System.Text.RegularExpressions.Regex(@"\\u([0-9A-F]{4})", System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Compiled).Replace(
                         source, x => string.Empty + Convert.ToChar(Convert.ToUInt16(x.Result("$1"), 16)));
        }
        /// <summary>  
        /// 按字符串长度切分成数组  
        /// </summary>  
        /// <param name="str">原字符串</param>  
        /// <param name="separatorCharNum">切分长度</param>  
        /// <returns>字符串数组</returns>  
        public static string[] SplitByLen(string str, int separatorCharNum)
        {
            if (string.IsNullOrEmpty(str) || str.Length <= separatorCharNum)
            {
                return new string[] { str };
            }
            string tempStr = str;
            List<string> strList = new List<string>();
            int iMax = Convert.ToInt32(Math.Ceiling(str.Length / (separatorCharNum * 1.0)));//获取循环次数  
            for (int i = 1; i <= iMax; i++)
            {
                string currMsg = tempStr.Substring(0, tempStr.Length > separatorCharNum ? separatorCharNum : tempStr.Length);
                strList.Add(currMsg);
                if (tempStr.Length > separatorCharNum)
                {
                    tempStr = tempStr.Substring(separatorCharNum, tempStr.Length - separatorCharNum);
                }
            }
            return strList.ToArray();
        }
        /// <summary>
        /// 替换字符串起始位置(开头)中指定的字符串
        /// </summary>
        /// <param name="s">源串</param>
        /// <param name="searchStr">查找的串</param>
        /// <param name="replaceStr">替换的目标串</param>
        /// <returns></returns>
        public static string TrimStarString(string s, string searchStr, string replaceStr)
        {
            var result = s;
            try
            {
                if (string.IsNullOrEmpty(result))
                {
                    return result;
                }
                if (s.Length < searchStr.Length)
                {
                    return result;
                }
                if (s.IndexOf(searchStr, 0, searchStr.Length, StringComparison.Ordinal) > -1)
                {
                    result = replaceStr + s.Substring(searchStr.Length);
                }
                return result;
            }
            catch (Exception e)
            {
                return result;
            }
        }

        public static string HexTo10(string str)
        {
            return Convert.ToInt32(str, 16).ToString();
        }


        private static bool checkqo(int i)
        {
            if (i % 2 == 0)
            {
                return true;
            }
            else
                return false;
        }
        /// <summary>
        /// 转身份证号
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string strToIdNumber(string str)
        {
            str = str.Substring(0, 36);
            int i = 1;
            string aaa = "";
            foreach (var a in str)
            {
                if (checkqo(i) == false)
                {
                    if (a == '3')
                    {
                        i++;
                        continue;
                    }
                }
                i++;

                aaa += a;
            }
            if (aaa.Length == 18)
                return aaa;
            else
            {
                return aaa.Substring(0, 17) + "X";
            }
        }
        #endregion

        #region 读取卡片Id号
        /// <summary>
        /// 读取卡片Id号
        /// </summary>
        /// <returns></returns>
        public ReacardNumOutput ReadIcNo()
        {
            ReacardNumOutput output = new ReacardNumOutput();
            output.msg = "读卡失败!";
            output.ret = 0;
            CardPerson persong = new CardPerson();
            try
            {
                short txtPort = 100;
                icdev = D8API.dc_init(txtPort, 115200);
                if (icdev <= 0)
                {
                    output.msg = "初始化读卡器失败!";
                    output.ret = -1;
                }
                else
                {
                    D8API.dc_beep(icdev, 10);
                    ulong icCardNo = 0;
                    int st = D8API.dc_card((Int16)icdev, '0', ref icCardNo);
                    if (st == 0)
                    {
                        output.cardno = icCardNo.ToString();
                        output.catcardno = icCardNo.ToString();
                        output.msg = "读卡成功!";
                        output.ret = 1;
                    }
                    if (st != 0)
                    {
                        output.msg = "寻卡失败,请正确放置卡片!";
                        output.ret = -2;
                    }
                }
                //关闭
                D8API.dc_exit((Int16)icdev);
            }
            catch (Exception ex)
            {
                //关闭
                D8API.dc_exit((Int16)icdev);
            }
            return output;
        }
        #endregion
    }
}
